package ray.surface;

import java.text.DecimalFormat;

import ray.math.Point3;
import ray.math.Ray;
import ray.math.Tuple3;
import ray.math.Vector3;

public class Box extends Surface {
	
	/* The corner of the box with the smallest x, y, and z components. */
	protected final Point3 minPt = new Point3();
	public void setMinPt(Point3 minPt) { this.minPt.set(minPt); }

	/* The corner of the box with the largest x, y, and z components. */
	protected final Point3 maxPt = new Point3();
	public void setMaxPt(Point3 maxPt) { this.maxPt.set(maxPt); }

	public Box() { }

	/**
	 * @see Object#toString()
	 */
	public String toString() {
		return "box " + minPt + " " + maxPt + " " + shader + " end";
	}
	
	public double rayCollision(Vector3 ray,Point3 viewPoint){
		double tNear = Double.NEGATIVE_INFINITY;
		double tFar = Double.POSITIVE_INFINITY;
		
		double[] pArr = {viewPoint.x,viewPoint.y,viewPoint.z};
		double[] minPtArr = {minPt.x,minPt.y,minPt.z};
		double[] maxPtArr = {maxPt.x,maxPt.y,maxPt.z};
		double[] rayArr = {ray.x,ray.y,ray.z};
		
		for(int i = 0;i<pArr.length;i++){
			if(rayArr[i] == 0){
				if(pArr[i]<minPtArr[i] || pArr[i]>maxPtArr[i]){
					return 0.0;
				}
			}
			else {
				double t1 = (minPtArr[i] - pArr[i])/rayArr[i];
				double t2 = (maxPtArr[i] - pArr[i])/rayArr[i];
				double temp;
				if(t1>t2){
					temp = t1;
					t1 = t2;
					t2 = temp;
				}
				if(t1>tNear){
					tNear = t1;
				}
				if(t2<tFar){
					tFar = t2;
				}
				if(tNear>tFar){
					return 0.0;
				}
				if(tFar<0){
					return 0;
				}
			}
		}
		return tNear;
	}
	
	public double rayCollision(Ray ray){
		return rayCollision(ray.direction,ray.origin);
	}
	
	public Vector3 calcUnitNormal(Point3 point){
		Vector3 unitNormal = new Vector3();
		
		DecimalFormat dF = new DecimalFormat("#.##");
		
		Point3 fPoint = new Point3(Double.valueOf(dF.format(point.x)).doubleValue(),
				Double.valueOf(dF.format(point.y)).doubleValue(),
				Double.valueOf(dF.format(point.z)).doubleValue());
		
		if(fPoint.x == minPt.x || fPoint.x == maxPt.x){
			unitNormal.set(new Tuple3(1,0,0));
		}
		else if(fPoint.z == minPt.z || fPoint.z == maxPt.z){
			unitNormal.set(new Tuple3(0,0,1));
		}
		else {
			unitNormal.set(new Tuple3(0,1,0));
		}
		
		unitNormal.normalize();
		
		return unitNormal;
	}
}
